﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DDD.Core {


    /// <summary>
    /// コリジョン ボリューム コンポーネント
    /// </summary>
    /// <remarks>
    /// <see cref="CollisionVolume"/> はコンポーネントの1種で、ノードにコリジョン領域と検出の機能を追加します。
    /// このコンポーネントがアタッチされたノードはコリジョン検出の対象になります。
    /// もしそうでなければ対象とはなりません。
    /// <para>
    /// <h3>k-DOP</h3>
    /// コリジョン領域は有効離散ポリトープ(v-DOP)で定義されます。
    /// (以降名称は基本的にk-DOPを使用します)
    /// DDDではk=26のk-DOPを使用します。
    /// v-DOP(v=26)はAABBの6面体をさらにコーナーカット(8面)、エッジカット(12面)したものです(6+8+12=26)。
    /// v-DOPは領域を使用する軸とその軸の下限、上限で定義されます。
    /// ここではk=26なので最大で13軸使用します。
    /// </para>
    /// <para>
    /// <h3>コリジョン検出</h3>
    /// 
    /// </para>
    /// </remarks>
    /// <seealso cref="CollisionShape"/>
    public class CollisionVolume : Component {

        #region Field
        CollisionShape collisionShape;
        #endregion

        #region Constructor
        /// <summary>
        /// コンストラクター
        /// </summary>
        /// <remarks>
        /// </remarks>
        public CollisionVolume () {
            this.collisionShape = new CollisionShape ();
        }
        #endregion

        #region Property

        /// <summary>
        /// コリジョン形状
        /// </summary>
        /// <remarks>
        /// このコリジョン形状をあらわす <see cref="CollisionShape"/> 構造体を返します。
        /// コリジョン形状はk-DOP(v=26)で表されます。
        /// </remarks>
        public CollisionShape CollisionShape {
            get { return collisionShape; }
        }


        /// <inheritodc/>
        public override IEnumerable<Object> References {
            get {
                return base.References;
            }
        }
        #endregion

        #region Method
        /// <summary>
        /// コリジョン形状の設定
        /// </summary>
        /// <remarks>
        /// このコリジョンボリューム コンポーネントで使用するコリジョン形状を設定します。
        /// コリジョン形状はk=26のK-DOPで表され、使用する軸のビットを立てた <paramref name="orientation"/> と、
        /// 使用する軸について軸に沿った下限、上限を設定します。
        /// 空のコリジョン形状をセットし直すには <paramref name="orientaion"/> = 0 を指定します。
        /// </remarks>
        /// <param name="orientation">使用する軸</param>
        /// <param name="min">下限値の配列</param>
        /// <param name="max">上限値の配列</param>
        public void SetCollisionShape (int orientation, float[] min, float[] max) {
            if (min == null) {
                throw new ArgumentNullException ("Min is null");
            }
            if (max == null) {
                throw new ArgumentNullException ("Max is null");
            }
            if (min.Length < 13) {
                throw new ArgumentException ("Min is less than required.");
            }
            if (max.Length < 13) {
                throw new ArgumentException ("Max is less than required.");
            }

            this.collisionShape = new CollisionShape (orientation, min, max);
        }

         /// <inheritdoc/>
        public override string ToString () {
            return string.Format("CollisionVolume: Orientaion={0}, Min={1}, Max={2}", CollisionShape.Orientaion, CollisionShape.Min, CollisionShape.Max);
        }
        #endregion
    }
}
